<template>
  <div>
    <div v-if="config.annoTree?.displayAsTree === true" class="w-full justify-center flex">
      <AnnoM2mTree :options="option" :data="data" />
    </div>
    <div v-else-if="config.annoTree?.displayAsTree === false" class="w-full justify-center flex">
      <AnnoM2mTable
        :tableConfig="tableConfig"
        ref="M2mTable"
        :isAdd="isAdd"
        @add-m2m="addM2m"
        @delete-rows="deleteRows"
      />
    </div>
    <Loading v-else :loading="true" tip="加载中" />
    <AnnoM2mModal @register="registerM2mModal" @success="addRows" />
  </div>
</template>

<script lang="ts" setup>
  import { AnEntity, ColumnButton } from '@/api/sys/model/entitysModel';
  import { getEntity, getTableData, deleteM2m, addM2ms } from '@/api/sys/anno';

  import { getAnnoSearchForm, getColumns } from '@/utils/anno';
  import AnnoM2mModal from './AnnoM2mModal.vue';
  import { useModal } from '@/components/Modal';
  import { useMessage } from '@/hooks/web/useMessage';
  import AnnoM2mTable from './AnnoM2mTable.vue';
  import AnnoM2mTree from './AnnoM2mTree.vue';
  // @ts-ignore
  import { Loading } from '/@/components/Loading';
  import { useAppInject } from '@/hooks/web/useAppInject';

  const { getIsMobile } = useAppInject();
  const { createMessage } = useMessage();

  type mountType = 'table' | 'tree';
  interface props {
    option: ColumnButton | null;
    data: any | null;
    isAdd: boolean | null;
  }
  const $props = defineProps<props>();
  watch(
    () => $props.option,
    (newVal) => {
      if (newVal) {
        loadConfig(newVal.m2mJoinButton.joinTargetClazz);
      }
    },
    { immediate: true },
  );
  const config = reactive<Partial<AnEntity>>({});

  const [registerM2mModal, { openModal: openM2modal }] = useModal();
  const addM2m = () => {
    openM2modal(true, {
      props: toRaw($props.data),
      option: toRaw($props.option),
      isAdd: true,
    });
  };

  function loadConfig(clazz: string) {
    getEntity(clazz).then((res) => {
      Object.assign(config, res);
      nextTick(() => {
        mountM2m(res.annoTree.displayAsTree ? 'tree' : 'table', res, $props.data);
      });
    });
  }
  const extParams = computed(() => {
    return {
      annoM2mId: $props.option!.m2mJoinButton.id,
      joinValue: $props.data[$props.option!.m2mJoinButton.joinThisClazzField],
      reverseM2m: $props.isAdd,
    };
  });
  const tableConfig = reactive({});
  const M2mTable = ref<InstanceType<typeof AnnoM2mTable> | null>(null);
  function mountM2m(type: mountType, res: AnEntity, data: any) {
    if (type == 'table') {
      mountTable(res);
    } else if (type == 'tree') {
      mountTree();
    } else {
      const res: never = type;
      return res;
    }
  }

  const mountTable = (res: AnEntity) => {
    const api = getTableData(
      res.entityName!,
      res.annoTree.parentKey,
      res.annoTree.key,
      res.annoTree.displayAsTree,
    );
    const searchFormFields = getAnnoSearchForm(res.columns, getIsMobile);
    Object.assign(tableConfig, {
      tableKey: $props.option!.m2mJoinButton.joinTargetClazz,
      pagination: {
        pageSize: res.annoTree.displayAsTree ? 99999 : 20,
      },
      api,
      size: 'small',
      rowSelection: {},
      scroll: { x: true, y: 250 },
      isTreeTable: res.annoTree.displayAsTree,
      rowKey: res.pkColumn.javaName,
      columns: getColumns(res.columns),
      formConfig: {
        rowProps: { gutter: 16, justify: 'start' },
        labelWidth: 100,
        showAdvancedButton: false,
        labelAlign: 'left',
        autoAdvancedLine: 50,
        schemas: searchFormFields,
        autoSubmitOnEnter: true,
      },
      useSearchForm: searchFormFields.length > 0,
      showTableSetting: true,
      bordered: true,
      searchInfo: extParams,
      handleSearchInfoFn(info) {
        return info;
      },
    });
  };

  const mountTree = () => {};

  const deleteRows = (rowKeys) => {
    if (rowKeys.length < 1) return;
    deleteM2m($props.option!.m2mJoinButton.mediumTableClazz, {
      annoM2mId: $props.option!.m2mJoinButton.id,
      targetJoinValue: rowKeys,
      thisJoinValue: $props.data[$props.option!.m2mJoinButton.joinThisClazzField],
    }).then((res) => {
      M2mTable.value!.reload();
      createMessage.success('取消关联成功');
    });
  };
  const addRows = (rowKeys: any[]) => {
    if (rowKeys.length < 1) return;
    addM2ms($props.option!.m2mJoinButton.mediumTableClazz, {
      annoM2mId: $props.option!.m2mJoinButton.id,
      targetJoinValue: rowKeys,
      thisJoinValue: $props.data[$props.option!.m2mJoinButton.joinThisClazzField],
    }).then((res) => {
      M2mTable.value!.reload();
      createMessage.success('关联成功');
    });
  };

  interface Emits {
    (e: 'addM2m', value: any[]): void;
  }
  const emit = defineEmits<Emits>();
  const getAddRows = () => {
    const rowKeys = M2mTable.value!.getSelectRowKeys();
    if (rowKeys.length < 1) return;
    return rowKeys;
  };
  const clearSelectedRowKeys = () => {
    M2mTable.value!.clearSelectedRowKeys();
  };
  defineExpose({ getAddRows, clearSelectedRowKeys });
</script>
<style lang="less" scoped></style>
